// npm install mqtt -S
import * as mqtt from "mqtt/dist/mqtt.min";
import type {MqttClient, OnMessageCallback} from "mqtt";
import {ref, onUnmounted} from "vue";
// 连接字符串, 通过协议指定使用的连接方式
// ws 未加密 WebSocket 连接
// wss 加密 WebSocket 连接
// mqtt 未加密 TCP 连接
// mqtts 加密 TCP 连接
// wxs 微信小程序连接
// alis 支付宝小程序连接
class MQTT {
  url: string; // mqtt地址
  //长链接单个订阅
  topic: string[]; //订阅主题地址
  client!: MqttClient;
  constructor(topic: string[], dataObj: any) {
    this.topic = topic;
    // 虽然是mqtt但是在客户端这里必须采用websock的链接方式
    this.url = dataObj.url;
  }

  //初始化mqtt
  init(obj: Object) {
    const options = {
      clean: true, // 保留会话
      // 认证信息
      clientId: obj.clientId, //唯一值
      username: obj.userName, //用户名 不用的话什么也不用填
      password: obj.password, //密码 不用的话什么也不用填
      connectTimeout: 4000, // 超时时间
      reconnectPeriod: 4000 // 重连时间间隔
    };
    this.client = mqtt.connect(this.url, options);
    this.client.on("error", (error: any) => {
      console.log("错误信息");
    });
    this.client.on("reconnect", (error: Error) => {
      console.log("重连");
    });
  }
  //取消订阅
  unsubscribes(topic: string[]) {
    topic.forEach((item) => {
      this.client.unsubscribe(item, (error: Error) => {
        if (!error) {
          console.log("取消订阅成功");
        } else {
          console.log("取消订阅失败");
        }
      });
    });
  }
  //连接
  link(topic: string[]) {
    topic.forEach((item) => {
      this.client.on("connect", () => {
        this.client.subscribe(item, (error: any) => {
          if (!error) {
            console.log("订阅成功");
          } else {
            console.log("订阅失败");
          }
        });
      });
    });
  }
  //收到的消息
  get(callback: OnMessageCallback) {
    this.client.on("message", callback);
  }
  //结束链接
  over() {
    this.client.end();
  }
}

export default function useMqtt() {
  const PublicMqtt = ref<MQTT | null>(null);
  let topicData: string[];

  const startMqtt = (
    dataObj: Object,
    val: string[],
    callback: OnMessageCallback
  ) => {
    topicData = val;
    //设置订阅地址
    PublicMqtt.value = new MQTT(val, dataObj);
    // console.log(PublicMqtt.value)
    //初始化mqtt
    PublicMqtt.value.init(dataObj);
    //链接mqtt
    PublicMqtt.value.link(val);
    getMessage(callback);
  };
  const getMessage = (callback: OnMessageCallback) => {
    // PublicMqtt.value?.client.on('message', callback);
    PublicMqtt.value?.get(callback);
  };
  onUnmounted(() => {
    //页面销毁结束订阅
    if (PublicMqtt.value) {
      PublicMqtt.value.unsubscribes(topicData);
      PublicMqtt.value.over();
    }
  });

  return {
    startMqtt
  };
}
